02. Testing and Class Design

Testing and Class Design

ND079 JPND C3 L5 A02 Testing And Class Design V2

Testing Around Dependencies

How do we test UserService.fancyBusiness without relying on the behavior of SalesService.fizzBuzz?

  1. Create a custom SalesService that does what we tell it to do.
  2. Get the fake SalesService into UserService so it uses that instead of its normal behavior.

Use Interfaces to Create Fake Services

public interface SalesService {
   String fizzBuzz(int i);
}

Creating an interface for Services makes it easy to create fake versions of those Services. This FakeSalesService returns whatever value was used to create it when fizzBuzz is called.

public class FakeSalesService implements SalesService {
   private String returnValue;
   public FakeSalesService(String returnValue) {
       this.returnValue = returnValue;
   }
   @Override
   public String fizzBuzz(int i) {
       return returnValue;
   }
}

Decouple Dependencies

Now that we have an interface, we should update UserService so that we can replace the SalesService it uses with the one we want.

public class UserServiceImpl implements UserService {
   SalesService salesService;

   public UserServiceImpl(SalesService salesService) {
      this.salesService = salesService;
   }

   public String fancyBusiness(int n) {/* hidden */  }
   // remainder omitted
}

Test!

We're finally ready to test. This unit test looks for the first requirement:

  1. If SalesService.fizzBuzz returns “Fizz”, “Buzz”, or “FizzBuzz”, then fancyBusiness just returns that string.
@ParameterizedTest
@ValueSource(strings={"Fizz", "Buzz", "FizzBuzz"})
public void fancyBusinessFakeFizzBuzz_getsFizzBuzzString_returnsSameString(
                                                      String returnString) {

   SalesService salesService = new FakeSalesService(returnString);
   UserService userService = new UserServiceImpl(salesService);

   // which number we pass doesn't matter, because we're controlling 
   // the return value of FizzBuzz
   assertEquals(returnString, userService.fancyBusiness(1));
}

This test creates a FakeSalesService that will always return the string provided from our @ValueSource. When we call userService.fancyBusiness(1), the user service will then call the fizzBuzz method on the fake sales service. We then use assertEquals to verify that the fancyBusiness returns the unmodified string for "Fizz", "Buzz", and "FizzBuzz".